#include "CharacterRecord.h"
#include "TraitException.h"

#include <QVariant>
#include <QLabel>
#include <QDebug>

CharacterRecord::CharacterRecord()
{
}

CharacterRecord::~CharacterRecord()
{
}

void CharacterRecord::apply(QWidget *sheet) const
{
    QList<QLabel *> fields = sheet->findChildren<QLabel *>();
    Q_ASSERT(fields.count());
    QList<QLabel *>::Iterator it = fields.begin();
    for ( ; it != fields.end(); ++it )
    {
        QVariant propV = (*it)->property("sourceProperty");
        if (!propV.isValid())
            continue;
        QString prop = propV.toString();
        QVariant val = property(prop.toLocal8Bit());
        if (val.isValid())
            (*it)->setText(val.toString());
        else
            qWarning() << "sourceProperty" << prop << "not found in character record";
    }
}

QString CharacterRecord::height() const
{
    int h = intProps["height"]; // number of inches
    QString feet = QString::number(h / 12);
    QString inches = QString::number(h % 12);
    return QString("%1ft %2in").arg(feet).arg(inches);
}

void CharacterRecord::setHeight(const QString &s)
{
    QRegExp rx("(\\d+)ft (\\d+)in");
    int ix = rx.indexIn(s);
    if (ix < 0)
        throw TraitException(tr("Could not parse height from %1").arg(s));
    QString feet = rx.cap(1);
    QString in = rx.cap(2);
    bool ok;
    int feetNum = feet.toInt(&ok);
    if (!ok)
        throw TraitException(tr("Could not parse feet from %1").arg(s));
    int inNum = in.toInt(&ok);
    if (!ok)
        throw TraitException(tr("Could not parse inches from %1").arg(s));
    intProps["height"] = feetNum * 12 + inNum;
}


QString CharacterRecord::weight() const
{
    int h = intProps["weight"]; // number of pounds
    return QString("%1lb").arg(h);
}

void CharacterRecord::setWeight(const QString &s)
{
    QRegExp rx("(\\d+)lb");
    int ix = rx.indexIn(s);
    if (ix < 0)
        throw TraitException(tr("Could not parse weight from %1").arg(s));
    QString weight = rx.cap(1);
    bool ok;
    int poundsNum = weight.toInt(&ok);
    if (!ok)
        throw TraitException(tr("Could not parse pounds from %1").arg(s));
    intProps["weight"] = poundsNum;
}

int CharacterRecord::armourClass() const
{
    return acAbilBonus() + acClassBonus() + acFeatBonus()
            + acMiscBonus1() + acMiscBonus2()
            + tenPlusHalfLevel();
}

int CharacterRecord::acAbilBonus() const
{
    if (armourWeight() == DndData::HEAVY_ARMOUR)
        return 0;
    return qMax(intMod(), dexMod());
}

int CharacterRecord::fortitude() const
{
    return fortAbilBonus() + fortClassBonus()
            + fortFeatBonus() + fortMiscBonus1()
            + fortMiscBonus2() + tenPlusHalfLevel();
}

int CharacterRecord::reflex() const
{
    return refAbilBonus() + refClassBonus()
            + refFeatBonus() + refMiscBonus1()
            + refMiscBonus2() + tenPlusHalfLevel();
}

int CharacterRecord::will() const
{
    return willAbilBonus() + willClassBonus()
            + willFeatBonus() + willMiscBonus1()
            + willMiscBonus2() + tenPlusHalfLevel();
}
